<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    html,body{margin: 0;padding: 0;}
    .cvs{display:block;}
  </style>
</head>
<body>
  <canvas class="cvs"></canvas>
</body>
<script>

  const cvs = document.querySelector(".cvs");
  cvs.width = window.innerWidth;
  cvs.height = window.innerHeight;
  const ctx = cvs.getContext("2d");

  // 我的飞机，一个，单例
  const myPlane = {
    x: 100,
    y: 200,
    bullets: [],
    addEvent(){
      const that = this;
      cvs.addEventListener("mousemove", function(eve){
        const e = eve || window.event;
        that.x = e.offsetX;
        that.y = e.offsetY;
      })
      cvs.addEventListener("click", async function(){
        // 创建子弹
        const bullet = await newImg("./images/bullet.png");
        that.bullets.push(new Bullet({
          img: bullet,
          me: that,
          speed: 10
        }));
      })
    }
  }

  // 子弹，多个，工厂
  class Bullet{
    constructor({ img, me, speed }){
      this.img = img;
      this.me = me;
      this.x = me.x - img.width / 2;
      this.y = me.y - me.h/2 - img.height;
      this.w = img.width;
      this.h = img.height;
      this.speed = speed;
    }
    move(){
      this.y -= this.speed;

      if(this.y < 0){
        this.die();
      }
    }
    die(){
      let i=0;
      myPlane.bullets.some((val,idx)=>{
        i = idx;
        return val === this;
      })
      myPlane.bullets.splice(i, 1);
    }
  }

  // 敌机，多个，工厂
  class Enemy{
    constructor({ img, hp }){
      this.img = img;
      this.hp = hp
      this.x = random(0, cvs.width-img.width);
      this.y = -img.height;
      this.w = img.width;
      this.h = img.height;

      switch(this.hp){
        case 1:
          this.speed = 3;
          break;
        case 2:
          this.speed = 2;
          break;
        case 3:
          this.speed = 1;
          break;
      }
    }
    move(){
      this.y += this.speed;

      myPlane.bullets.forEach(val=>{
        // val.x, val.y
        // this.x, this.y
        if(val.y < this.y+this.h && this.y < val.y+val.h && val.x < this.x+this.w && this.x < val.x+val.w){
          val.die();
          
          this.hp--;

          if(this.hp === 0){
            // 计分
            this.die();
          }
        }
      })

      if(this.y > cvs.height){
        this.die();
      }
    }
    die(){
      let i=0;
      enemys.some((val,idx)=>{
        i = idx;
        return val === this;
      })
      enemys.splice(i, 1);
    }
  }

  myPlane.addEvent();

  const enemys = [];
  
  ;(async function(){
    const me = await newImg("./images/me.png");
    myPlane.img = me;
    myPlane.w = me.width;
    myPlane.h = me.height;

    const plane1 = await newImg("./images/plane1.png");
    const plane2 = await newImg("./images/plane2.png");
    const plane3 = await newImg("./images/plane3.png");

    // enemys.push(new Enemy({
    //   img: plane1,
    //   hp: 1
    // }));
    
    let i=0;
    function fn(){
      i++;
      ctx.clearRect(0, 0, cvs.width, cvs.height);

      if( i%60 === 0 && Math.random() > 0.4 ){
        enemys.push(new Enemy({
          img: plane1,
          hp: 1
        }));
      }
      if( i%120 === 0 && Math.random() > 0.6 ){
        enemys.push(new Enemy({
          img: plane2,
          hp: 3
        }));
      }
      if( i%300 === 0 && Math.random() > 0.8 ){
        enemys.push(new Enemy({
          img: plane3,
          hp: 5
        }));
      }

      ctx.drawImage(
        me, 
        myPlane.x-me.width/2, myPlane.y-me.height/2,
        me.width, me.height
      );

      myPlane.bullets.forEach(val=>{
        ctx.drawImage(
          val.img, 
          val.x, val.y,
          val.w, val.h
        );
        val.move();
      })

      enemys.forEach(val=>{
        ctx.drawImage(
          val.img, 
          val.x, val.y,
          val.w, val.h
        );
        val.move();
      })

      requestAnimationFrame( fn );
    }

    fn();
  })();

  // 延展功能：
    // 计分
    // 开始
    // 暂停
    // 死亡效果：爆炸图
    // 限时大礼包（敌机）
    // 关卡
    // boss（敌机）

  function newImg( src ){
    const img = new Image();
    img.src = src;
    return new Promise(resolve=>{
      img.onload = function(){
        resolve(this);
      }
    })
  }
  

  function random(a,b){
    return Math.round(Math.random()*(a-b)+b);
  }
</script>
</html>